Replace the matching certificate slot instead of appending a duplicate - #1152
Replace the matching certificate slot instead of appending a duplicate#1152yosuke-wolfssl wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull request overview
Fixes SetHostCertificate() so reloading a host certificate replaces an existing matching certificate slot (instead of always appending a duplicate), and ensures DER is freed on the “table full” error path. This prevents stale certificates from continuing to be served after reload and avoids slot exhaustion/leaks.
Changes:
src/internal.c: Choose the destination slot based on the search result (replace vs append) and freederwhenWOLFSSH_MAX_PVT_KEYSis exceeded.tests/api.c: Extendtest_wolfSSH_CTX_UseCert_buffer()to assert replacement behavior and cover the table-full error path.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/internal.c | Fixes certificate slot selection to enable in-place replacement and frees DER on overflow error path. |
| tests/api.c | Adds assertions ensuring reload replaces instead of appends, plus a regression check for the overflow/free-on-error path. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #1152
Scan targets checked: wolfssh-bugs, wolfssh-src
Findings: 3
3 finding(s) posted as inline comments (see file-level comments below)
This review was generated automatically by Fenrir. Findings are non-blocking.
5a84d26 to
abcc3be
Compare
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #1152
Scan targets checked: wolfssh-bugs, wolfssh-src
Findings: 1
1 finding(s) posted as inline comments (see file-level comments below)
This review was generated automatically by Fenrir. Findings are non-blocking.
abcc3be to
2f5e86a
Compare
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #1152
Scan targets checked: wolfssh-bugs, wolfssh-src
Findings: 2
2 finding(s) posted as inline comments (see file-level comments below)
This review was generated automatically by Fenrir. Findings are non-blocking.
2f5e86a to
bbdcb18
Compare
There was a problem hiding this comment.
Can you also fix the case when UpdateHostCertificates returns error? I think we need to decrement privateKeyCount and cleanup other parts of the table
There was a problem hiding this comment.
Fixed by reordering rather than adding rollback: SetHostCertificate() now calls
UpdateHostCertificates() before committing anything to the slot. That call is the
only fallible step (its sole failure return is the key-copy WMALLOC), and it does
not touch the slot's cert or publicKeyFmt -- so on failure the DER is freed, the
error returns, and count/slot/algorithms are exactly as before.
The append path was the real hazard: the slot was already counted and marked with
the x509v3 algorithm while its key was still NULL. RefreshPublicKeyAlgo() is
skipped on the error path, but any later successful load reruns it and would
advertise an algorithm whose slot has no key. The replace path is covered too --
the old certificate is no longer freed before the fallible call.
Not adding a unit test. The path is unreachable except under allocation failure,
and driving it needs a process-wide allocator hook keyed on byte size; I
prototyped that and it works, but it depends on wolfSSL's internal allocation
sizes and os-check runs against the two newest wolfSSL releases resolved at run
time, so a wolfSSL release could break our CI on its own. There is also no error
branch left to test -- nothing is mutated before the fallible call. The ordering
requirement is stated in the comment above it.
bbdcb18 to
99512e2
Compare
|
Hi @padelsbach , |
Problem
SetHostCertificate()never replaced an existing certificate. Its search looprecords a matching slot in
certIdx, butdestIdxis the loop counter and theloop has no
break, so on exit it always equalsctx->privateKeyCount— theappend slot.
pvtKeyis taken from there, whosepublicKeyFmtis alwaysID_NONE, making thepvtKey->publicKeyFmt == certIdreplace branch dead code;the
elsebranch then discards the search result withcertIdx = destIdx;.Reloading a certificate for an algorithm that already has one therefore appends
a duplicate slot instead of replacing it. KEX selects the signing slot with a
first-match-and-break scan, so the stale certificate at the lower index keeps
being served — a renewed certificate silently has no effect until restart. The
call still returns
WS_SUCCESS. Additional consequences: the old DER is neverfreed, the same
x509v3-*name is emitted twice inserver_host_key_algorithms, and each reload burns a slot untilWOLFSSH_MAX_PVT_KEYSis exhausted.Sibling
SetHostPrivateKey()gets this right — itswhileloop puts the matchtest in the loop condition, so it stops on the matching slot.
Fix (
src/internal.c)Select the destination slot from the search result before using it:
HINTISSET()is the file's existing sentinel idiom, andcertIdxis only everassigned an in-range index, so the replace branch becomes reachable and frees
the old DER in place. The append path is unchanged.
Also frees
deron thedestIdx >= WOLFSSH_MAX_PVT_KEYSpath — ownershiptransfers from
wolfSSH_ProcessBuffer(), which does not free on error. Thatmatches what
SetHostPrivateKey()already does, and the fix makes the pathgenuinely reachable.
Closes F-8810.
Tests (
tests/api.c)Extended
test_wolfSSH_CTX_UseCert_buffer(), which already loaded the samecertificate as PEM then DER but never checked the bookkeeping. Now asserts
privateKeyCountis unchanged, the slot holds a different pointer, andpublicKeyAlgoCount == 1. Added a table-full case assertingWS_CTX_KEY_COUNT_Eto cover the free-on-error path.Verification
make check: 11 passed, 1 skipped, 0 failed (from a clean rebuild).1 != 2; injecting a secondWFREEon the error path trips ASan atSetHostCertificate internal.c:2386, pinning the test to that branch.gcc-13 -Werroracross 6 configs, including one with X.509 certsdisabled.